<template>
  <component :is="com" :schema="schema" v-if="visible">
    <Body :body="props.schema.body" />
    <template v-for="[slotName, slotValue] of Object.entries(slots)" :key="slotName" #[slotName]>
      <Body :body="slotValue" />
    </template>
  </component>
</template>

<script setup>
import { ref, reactive, watchEffect, getCurrentInstance } from 'vue'
import Body from './container/body/index.vue'
import { watchText } from './common/util'

const instance = getCurrentInstance()

const containerModules = import.meta.globEager('./container/*/index.vue')
const formModules = import.meta.globEager('./form/*/index.vue')
const otherModules = import.meta.globEager('./other/*/index.vue')
const components = {}

function parseCom(modules) {
  Object.keys(modules).forEach((key) => {
    const name = key.replace(/\.\/(.*)\/(.*)\/index\.vue/, '$2')
    components[name] = modules[key]?.default || modules[key]
  })
}

parseCom(containerModules)
parseCom(formModules)
parseCom(otherModules)

defineOptions({
  name: 'LowCode'
})
const props = defineProps({
  schema: {
    type: Object,
    required: true
  }
})

const com = ref()
const slots = reactive({})
const visible = ref(true)

watchEffect(() => {
  const schema = props.schema
  const tag = getComponentType(schema.type)
  com.value = components[tag]

  const attrSlots = schema.slots || {}
  Object.entries(attrSlots).map(([key, value]) => {
    slots[key] = value
  })

  if (schema.visibleOn) {
    watchText(schema.visibleOn, instance, visible)
  }

})

function getComponentType(type) {
  let comType = type

  if (comType.startsWith('input')) {
    comType = 'input'
  } else if (comType === 'link' || comType === 'button') {
    comType = 'action'
  } else if (comType.startsWith('el-') || comType.startsWith('vxe-')) {
    comType = 'lib'
  }

  if (comType) {
    if (!components[comType]) {
      comType = 'native'
    }
  }
  return comType
}
</script>
